package phrasal_verbs_learner;
import java.io.*;
import java.util.Random;
public class Phrasal_verbs_learner 
{
    public static String[][] wordlist; //here are all the phrasal verbs devided into russian and english parts
    public static int quantity; //the number of words in vocabulary
    public static int[] priorities; //the chances of verbs to be asked
    public static double inferior_limit = 0.5; //represents persentage necessary to get +1 in priorities in combat mode
    public static Boolean hard_mode = false;//in this mode you are going to be asked all the alternatives
    public static void main(String[] args) throws IOException
    {
        BufferedReader fr = new BufferedReader(new FileReader("INPUT.TXT"));
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in, "windows-1251"));
        Random random = new Random();
        quantity = Integer.valueOf(fr.readLine()); 
        makeGlobalList(fr);
        Boolean finished = false; //when true, the programm stops
        String command = "empty";
        writeln("Write 'help' to get the command list");
        while(!finished)
        {
            if(!command.equals("quit"))
            {
                writeln("");
                writeln("Write the command: ");
                command = br.readLine();
                if(command.equals("ask"))
                {
                    ask(random, br, -1);
                }
                if(command.equals("add"))
                {
                    add(br);
                }
                if(command.equals("help"))
                {
                    help();
                }
                if(command.equals("update"))
                {
                    changeVocabularyFile();
                    writeln("Successfully updated!");
                }
                if(command.equals("edit"))
                {
                    edit(br);
                }
                if(command.equals("ask verb"))
                {
                    askVerb(br, random);
                }
                if(command.equals("ask preposition"))
                {
                    askPreposition(br, random);
                }
                if(command.equals("test verb"))
                {
                    testVerb(random, br);
                }
                if(command.equals("test preposition"))
                {
                    testPreposition(random, br);
                }
                if(command.equals("all vocabulary"))
                {
                    listTheWholeVocabulary();
                }
                if(command.equals("hard mode on"))
                {
                    hard_mode = true;
                    writeln("Activating resident combat program in genocide mode...Combat open.");
                }
                if(command.equals("hard mode off"))
                {
                    hard_mode = false;
                    writeln("Hard mode off. Positive.");
                }
                if(command.equals("set inferior limit"))
                {
                    writeln("write down the value of inferior limit, a number between 0 and 1");
                    setInferiorLimit(br);
                }
                else
                {
                    if(command.isEmpty())
                    {
                        writeln("No command found. "
                                + "Write 'help' to get the command list");
                    }
                }
            }
            else
            {
                finished = true;
            }
        }
        changeVocabularyFile();
    }
    
    public static void makeGlobalList(BufferedReader fr) throws IOException
    {
        String[] list = getStringArray(quantity, fr);
        int L = list.length; //capitatal "L" differs from "1" unlike "l"
        wordlist = new String[L][2];
        priorities = new int[L];
        String[] english_russian_priority_part = new String[3];
        for(int i = 0; i < L; i++)
        {
            english_russian_priority_part = getEnglishRussianPriorityPart(list[i]);
            wordlist[i][0] = english_russian_priority_part[0];
            wordlist[i][1] = english_russian_priority_part[1];
            priorities[i] = Integer.valueOf(english_russian_priority_part[2]);
        }
    }
        
    public static void changeVocabularyFile() throws IOException
    {
        BufferedWriter fw = new BufferedWriter(new FileWriter("INPUT.TXT"));
        fw.write(Integer.toString(quantity));
        fw.newLine();
        for(int i = 0; i < quantity; i++)
        {
            fw.write(wordlist[i][0] + " " + wordlist[i][1] + " " + Integer.toString(priorities[i]));
            fw.newLine();
        }
        fw.close();
    }
    
    public static void ask(Random random, BufferedReader br, int number) throws IOException
    {
        if(number == -1) //-1 for a random verb considering priorities
        {
            number = getPriorityRandomed(random);
        }
        writeln("What is the russian for " + wordlist[number][0] + " ?");
        
        String[] diff_meanings = wordlist[number][1].split("#");
        String[] sinonims;
        int l = diff_meanings.length;
        String[][] alternatives = new String[l][];
        for(int i = 0; i < l; i++)
        {
            sinonims = diff_meanings[i].split("/");
            alternatives[i] = sinonims;
        }
        if(!hard_mode)
        {
            combatClose(alternatives, br, number, l);
        }
        else
        {
            combatOpen(alternatives, br, number, l);
        }
    }
        
    public static void add(BufferedReader br) throws IOException
    {
        String[][] wordlist_copy = new String[quantity][2];
        int[] priorities_copy = new int[quantity];
        for(int i = 0; i < quantity; i++)
        {
            wordlist_copy[i][0] = wordlist[i][0];
            wordlist_copy[i][1] = wordlist[i][1];
            priorities_copy[i] = priorities[i];
        }
        wordlist = new String[quantity + 1][2];
        priorities = new int[quantity + 1];
        for(int i = 0; i < quantity; i++)
        {
            wordlist[i][0] = wordlist_copy[i][0];
            wordlist[i][1] = wordlist_copy[i][1];
            priorities[i] = priorities_copy[i];
        }
        priorities[quantity] = 50;
        writeln("Write the phrasal verb: ");
        wordlist[quantity][0] = br.readLine();
        writeln("Write the translation: ");
        wordlist[quantity][1] = br.readLine();
        quantity++;
    }
    
    public static void edit(BufferedReader br) throws IOException
    {
        writeln("Write the verb that you would like to change in the form "
                + "you see it on the screen: ");
        String verb_to_change = br.readLine();
        for(int i = 0; i < quantity; i++)
        {
            if(wordlist[i][0].equals(verb_to_change))
            {
                writeln("Write the correct form of phrasal verb: ");
                wordlist[i][0] = br.readLine();
                writeln("Write the correct form of translation: ");
                wordlist[i][1] = br.readLine();
                break;
            }
        }
    }
    
    public static void askVerb(BufferedReader br, Random random) throws IOException
    {
        writeln("Write the verb without preposition to be asked: ");
        String verb = br.readLine();
        Boolean[] good_verbs = goodVerbs(verb);
        int number = Math.abs(random.nextInt()) % (quantity);
        while(good_verbs[number] == false)
        {
            number = Math.abs(random.nextInt()) % (quantity);
        }
        ask(random, br, number);
    }
    
    public static void askPreposition(BufferedReader br, Random random) throws IOException
    {
        writeln("Write the preposition you would like to be asked a phrasal "
                + "verb with: ");
        String preposition = br.readLine();
        int number = Math.abs(random.nextInt()) % (quantity);
        Boolean[] good_prepositions = goodPrepositions(preposition);
        while(good_prepositions[number] == false)
        {
            number = Math.abs(random.nextInt()) % (quantity);
        }
        ask(random, br, number);
    }
    
    public static void testVerb(Random random, BufferedReader br) throws IOException
    {
        writeln("Write the verb you want to be asked to all extends: ");
        String verb = br.readLine();
        Boolean[] good_verbs = goodVerbs(verb);
        int good_answers = 0;
        int bad_answers = 0;
        for(int i = 0; i < quantity; i++)
        {
            if(good_verbs[i])
            {
                int before = priorities[i];
                ask(random, br, i);
                int after = priorities[i];
                if(before > after || after == 1)
                {
                    good_answers++;
                }
                else
                {
                    bad_answers++;
                }
            }
        }
        writeln("The total result is " + 
                Double.toString((good_answers)*100/(good_answers + bad_answers)) + "%");
    }
    
    public static void testPreposition(Random random, BufferedReader br) throws IOException
    {
        writeln("Write the preposition you want to ba asked to all extends: ");
        String preposition = br.readLine();
        Boolean[] good_prepositions = goodPrepositions(preposition);
        int good_answers = 0;
        int bad_answers = 0;
        for(int i = 0; i < quantity; i++)
        {
            if(good_prepositions[i])
            {
                int before = priorities[i];
                ask(random, br, i);
                int after = priorities[i];
                if(before > after || after == 1)
                {
                    good_answers++;
                }
                else
                {
                    bad_answers++;
                }
            }
        }
        writeln("The total result is " + 
                Double.toString((good_answers)*100/(good_answers + bad_answers)) + "%");
    }
    
    public static Boolean[] goodVerbs(String verb)
    {
        String[] separated_verb;
        Boolean[] good_verbs = new Boolean[quantity];
        for(int i = 0; i < quantity; i++)
        {
            separated_verb = wordlist[i][0].split(" ");
            if(verb.equals(separated_verb[0]))
            {
                good_verbs[i] = true;
            }
            else
            {
                good_verbs[i] = false;
            }
        }
        return good_verbs;
    }
    
    public static Boolean[] goodPrepositions(String preposition)
    {
        String[] separated_verb;
        Boolean[] good_prepositions = new Boolean[quantity];
        for(int i = 0; i < quantity; i++)
        {
            good_prepositions[i] = false;
            separated_verb = wordlist[i][0].split(" ");
            int l = separated_verb.length;
            for(int k = 1; k < l; k++)
            {
                if(preposition.equals(separated_verb[k]))
                {
                    good_prepositions[i] = true;
                }
            }
        }
        return good_prepositions;
    }
        
    public static void help() //writes the command list
    {
        writeln("Write 'ask' to be asked a phrasal verb");
        writeln("Write 'ask verb' to be asked a phrasal verb with the verb you write");
        writeln("Write 'ask preposition' to be asked a phrasal verb "
                + "with the preposition you write");
        writeln("Write 'test verb' to be asked all the phrasal verbs with this verb");
        writeln("Write 'test preposition' to be asked all the phrasal verbs with this preposition");
        writeln("Write 'add' to add a new phrasal verb into buffer");
        writeln("Write 'update' to update the vocabulary file(might take some time)");
        writeln("Write 'edit' to update the incorrect verb");
        writeln("Write 'hard mode on' to be asked all the meanings of any phrasal verb");
        writeln("Write 'hard mode off' to turn off the hard mode");
        writeln("Write 'set inferior limit' to set the proportion of verbs to be answered truthfully for a full credit");
        writeln("Write 'quit' to finish the programm");
    }
    
    public static void listTheWholeVocabulary()
    {
        for(int i = 0; i < quantity; i++)
        {
            writeln(wordlist[i][0] + " " + wordlist[i][1]);
        }
    }
    
    public static void combatClose(String[][] alternatives, BufferedReader br, 
            int number, int l) throws IOException
    {
        String answer = br.readLine();
        Boolean right = false;
        int k;
        for(int i = 0; i < l; i++)
            {
                k = alternatives[i].length;
                for(int x = 0; x < k; x++)
                {
                    if(answer.equals(alternatives[i][x]))//looking through all possible alternatives
                    {
                        writeln("Right!");
                        right = true;
                        if(priorities[number] > 1)
                        {
                            priorities[number]--;
                        }
                        break;
                    }
                }
            }
            if(right == false)
            {
                writeln("Wrong!");
                writeln("The right answer was " + wordlist[number][1]);
                priorities[number]++;
            }
    }
    
    public static void combatOpen(String[][] alternatives, BufferedReader br, 
            int number, int senses) throws IOException //int senses represents quantity of diffrent senses
    {
        int k;
        String answer;
        Boolean[] right = new Boolean[senses];//useful for counting right answers
        for(int i = 0; i < senses; i++)
        {
            right[i] = false;
        }
        for(int q = 0; q < senses; q++)
        {
            writeln("Write one of transaltions with unique sense: ");
            answer = br.readLine();
            for(int i = 0; i < senses; i++) //checking if there is such a word in the list
            {
                k = alternatives[i].length;
                for(int o = 0; o < k; o++)
                {                    
                    if(answer.equals(alternatives[i][o]))
                    {
                        right[i] = true;
                        alternatives[i] = new String[0]; //the translation is removed with all sinonims
                        writeln("Right!");
                        o = k;
                        i = senses;
                    }
                }
            }
        }
        int good_answers = 0;
        for(int i = 0; i < senses; i++)
        {
            if(right[i])
            {
                good_answers++;
            }
        }
        if(good_answers != senses)
        {
            writeln("The full translation is " + wordlist[number][1] + " .");
        }
        double successfulness = Double.valueOf(good_answers) / Double.valueOf(senses);
        if(priorities[number] > 1 && successfulness > inferior_limit)
        {
            priorities[number]--;
        }
        if(successfulness < inferior_limit)
        {
            priorities[number]++;
        }
        writeln("The total result is " + Double.toString(successfulness * 100) + "%.");
        writeln("The minimum percentage of right answers is " 
                + Double.toString(inferior_limit* 100) + "%.");
    }

    public static boolean isEnglish(String word)
    {
        char[] letters = word.toCharArray();
        if((letters[0] > 96 && letters[0] < 123)||(letters[0] > 64 && letters[0] < 91))
        {
            return true;
        }
        else
        {
            return false;
        }
    }
    
    public static boolean isNumber(String word)
    {
        char[] letters = word.toCharArray();
        if(letters[0] > 47 && letters[0] < 58)
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    public static String[] getStringArray(int quantity, BufferedReader fr) throws IOException
    {
        String[] list = new String[quantity];
        for(int i = 0; i < quantity; i++)
        {
            list[i] = fr.readLine();
        }
        return list;
    }

    public static String[] getEnglishRussianPriorityPart(String raw) 
            //devides a String into three part depending on different language or priority number 
    {
        String[] devided = raw.split(" ");
        String english_part = "";
        String russian_part = "";
        String priority_part = "";
        int l = devided.length;
        for(int i = 0; i < l; i++)
        {
            if (isEnglish(devided[i]))
            {
                if(english_part.isEmpty())
                {
                    english_part = devided[i];
                }
                else
                {
                    english_part += " " + devided[i];
                }                    
            }
            else
            {
                if(!isNumber(devided[i]))
                {
                    if(russian_part.isEmpty())
                    {
                        russian_part = devided[i];
                    }
                    else
                    {
                        russian_part += " " + devided[i];
                    }
                }
                else
                {
                    priority_part = devided[i];
                }
            }
        }
        String[] english_russian_priority_part = new String[3];
        english_russian_priority_part[0] = english_part;
        english_russian_priority_part[1] = russian_part;
        english_russian_priority_part[2] = priority_part;
        return english_russian_priority_part;
    }
    
    public static int sumOfFirstN(int[] numbers, int N)
    {
        int answer = 0;
        for(int i = 0; i < N; i++)
        {
            answer += numbers[i];
        }
        return answer;
    }
    
    public static int getPriorityRandomed(Random random)
    {
        int number = 0;
        int priorities_sum = 0;
            for(int i = 0; i < quantity; i++)
            {
                priorities_sum += priorities[i];
            }
            int randomed = Math.abs(random.nextInt()) % (priorities_sum);
            number = 0;
            for(int i = 1; i <= quantity; i ++)
            {
                if(sumOfFirstN(priorities, i) < randomed)
                {
                    number++;
                }
            }
            return number;
    }
    
    public static int getLongestList(String[] diff_meanings)
    {
        String[] sinonims;
        int max = 0;
        int l = 0;
        int n = diff_meanings.length;
        for(int i = 0; i < n; i++)
        {
            sinonims = diff_meanings[i].split("/");
            l = sinonims.length;
            if(l > max)
            {
                max = l;
            }
        }
        return max;
    }
    
    public static void setInferiorLimit(BufferedReader br) throws IOException
    {
        inferior_limit = Integer.valueOf(br.readLine());        
    }
    public static void writeln(String str) //to make visual output easily changable
    {
        System.out.println(str);
    }
}